package vote

import (
	"awesomeTask/application/client"
	"awesomeTask/application/cron"
	"awesomeTask/application/timer"
	"awesomeTask/application/variable"
	awesomeTask "awesomeTask/commom"
	"awesomeTask/commom/MessageHelper"
	"awesomeTask/config"
	event2 "awesomeTask/system/event"
	"awesomeTask/system/kernel"
	"awesomeTask/system/log"
	"awesomeTask/system/registry"
	"awesomeTask/system/safe"
	"errors"
	"net"
	"reflect"
)

var voteList []map[string]interface{} = make([]map[string]interface{}, 0)

type vote interface {
	GenerateCode() int                          //生成发起选举的草案编号
	Launch()                                    //发起选举
	AcceptLaunchRequest(map[string]interface{}) //接受选举草案,并且生成自己向其他成员发送自己的选举结果 每个节点有两票
	ComputeVoteResult()                         //计算来自于其他节点的选举结果当前
	GetCurrentVoteCode()                        //获取当前的选举草案的编号
	buildVoteInfo(int) map[string]interface{}   //创建选举草案
}

type VoteHandler struct {
}

func (handler VoteHandler) ResetVotes() {
	voteList = make([]map[string]interface{}, 0)
}
func (handler VoteHandler) GenerateCode() int {
	safe.Lock()
	variable.VoteCode = variable.VoteCode + 1
	safe.Unlock()
	return variable.VoteCode
}
func (handler VoteHandler) buildVoteInfo(voteCode int) (map[string]interface{}, error) {
	info := make(map[string]interface{})
	info["suggests"] = []map[string]interface{}{
		{
			"listenIpAddress": config.GetConfigByKey("listenIpAddress"),
			"listenPort":      config.GetConfigByKey("listenPort"),
			"uniqueId":        config.GetConfigByKey("uniqueId"),
		},
	}
	info["voteCode"] = voteCode
	info["created_at"] = awesomeTask.Now()
	info["signer"] = config.GetConfigByKey("uniqueId").(string)
	node, err := GetBestNode()
	if err != nil {
		info["suggests"] = append(info["suggests"].([]map[string]interface{}), map[string]interface{}{
			"listenIpAddress": node.BindIp,
			"listenPort":      node.BindPort,
			"uniqueId":        node.UniqueId,
		})
	}
	return info, nil
}

/**
提议发起选举流程
*/
func (handler VoteHandler) Launch() {
	log.GetLogger().Info("调用选举")
	if variable.VoteIsFinish == false {
		timer.SetTimeOut(func() {
			if client.ServerCon == nil {
				variable.VoteIsFinish = true
			}
		}, 30)
	}
	if variable.VoteIsFinish == false || client.ServerCon != nil {
		return
	}
	log.GetLogger().Info("暂未寻找到主节点,开始执行选举流程")
	voteCode := handler.GenerateCode()
	votes, err := handler.buildVoteInfo(handler.GenerateCode())
	if err != nil {
		log.GetLogger().Error("选取中心中心节点失败:" + err.Error())
		return
	}
	variable.VoteIsFinish = false
	log.GetLogger().Error("已经将当前的状态设置为false")
	voteInfo := make(map[string]interface{})
	voteInfo["voteCode"] = voteCode
	voteInfo["created_at"] = awesomeTask.Now()
	voteInfo["signer"] = config.GetConfigByKey("uniqueId").(string)
	variable.ServerConnections.Range(func(key, value interface{}) bool {
		MessageHelper.SendEvent(variable.ON_LAUNCH_VOTE, votes, value.(net.Conn))
		return true
	})
	variable.ServerConnections.Range(func(key, value interface{}) bool {
		MessageHelper.SendEvent(variable.ON_ACCEPT_VOTE, votes, value.(net.Conn))
		return true
	})
}

func (handler *VoteHandler) Vote(voteCode int) {
	votes, err := handler.buildVoteInfo(voteCode)
	if err != nil {
		log.GetLogger().Error("选取中心中心节点失败:" + err.Error())
		return
	}
	voteInfo := make(map[string]interface{})
	voteInfo["voteCode"] = voteCode
	voteInfo["created_at"] = awesomeTask.Now()
	voteInfo["signer"] = config.GetConfigByKey("uniqueId").(string)
	variable.ServerConnections.Range(func(key, value interface{}) bool {
		MessageHelper.SendEvent(variable.ON_ACCEPT_VOTE, votes, value.(net.Conn))
		return true
	})
}

/**
处理接收到选举数据
*/
func (handler VoteHandler) AcceptLaunchRequest(params map[string]interface{}) {
	for _, item := range params["suggests"].([]interface{}) {
		safe.Lock()
		if len(voteList) == 0 {
			timer.SetTimeOut(func() {
				res, _ := handler.ComputeVoteResult()
				if res == config.GetConfigByKey("uniqueId") {
					ico := kernel.GetIocInstance()
					successed := ico.CallFunByName(ico.GetInstanceOrCreate("master"), "TryToBeMaster").([]reflect.Value)[0]
					if successed.Bool() {
						cron.RemoveAllTask()
						cron.LoadCronFromDataBase()
						log.GetLogger().Info("当前节点已经被选举为中心节点")
						variable.IsMaster = true
						event2.Dispatch(variable.ON_AS_MASTER)
					} else {
						log.GetLogger().Error("竞选主节点失败")
					}
					voteList = make([]map[string]interface{}, 0)
				}
			}, timer.Second*10)
		}
		voteList = append(voteList, item.(map[string]interface{}))
		safe.Unlock()
	}
}
func (handler VoteHandler) ComputeVoteResult() (string, error) {
	voteRes := make(map[string]int)
	for _, item := range voteList {
		key := item["uniqueId"].(string)
		_, ok := voteRes[key]
		if ok {
			voteRes[key] = voteRes[key] + 1
		} else {
			voteRes[key] = 1
		}
	}
	var maxVotes int = -1
	var maxVoteIpAddress string
	for key, value := range voteRes {
		if value > maxVotes {
			maxVotes = value
			maxVoteIpAddress = key
		}
	}
	if maxVotes == -1 {
		log.GetLogger().Error("计算投票结果失败")
		return "", errors.New("计算投票结果失败")
	}
	return maxVoteIpAddress, nil
}

func GetBestNode() (client.ClientHandle, error) {
	connectionInfo := make([]client.ClientHandle, 0)
	for _, node := range client.Nodes {
		if HasConnected(node.UniqueId) && node.IsInit {
			connectionInfo = append(connectionInfo, node)
		}
	}
	var score float64 = -1
	var node client.ClientHandle = client.ClientHandle{}
	node.IsInit = false
	for _, item := range connectionInfo {
		if score == -1 {
			score = item.GetCurrentResourceScore()
			node = item
			continue
		}
		nodeScore := item.GetCurrentResourceScore()
		if nodeScore > score {
			score = nodeScore
			node = item
		}
	}
	if node.IsInit == false {
		return node, errors.New("未能找到可用的连接节点,考虑使用单机模式运行!")
	}
	return node, nil
}
func HasConnected(uniqueID string) bool {
	_, ok := registry.GetConnectionByUniqueId(uniqueID)
	if ok == nil {
		return true
	}
	return false
}
